'use strict';

const crypto = require('crypto');
const svgCaptcha = require('svg-captcha')
const qiniu = require("qiniu");
const Controller = require('egg').Controller;

class CommonController extends Controller {

  tableName = ''
  jwtData = this.ctx.state.user //站点后台用户表uid 

  //获取店铺ID
  async getSiteId() {
    return await this.app.mysql.query('SELECT `site_id` FROM `user` WHERE `uid`=?', [this.jwtData.uid])
  }

  //成功响应
  async success(message = "获取成功", data = null) {
    return this.response(0, message, data);
  }

  //失败响应
  async error(message = "获取失败", data = null) {
    return this.response(-1, message, data);
  }

  //自定义默认成功响应
  async resData(code = 0, message = "获取成功", data = null) {
    return this.ctx.body = {
      code,
      message,
      data,
      timeStamp: new Date().getTime(),
    };
  }

  /* 
    添加数据

    options:object(数据)
  */
  async add(options) {
    let fields = Object.keys(options).join('`,`')
    let values = Object.values(options).join("','")
    return this.app.mysql.query('INSERT INTO `' + this.tableName + '` (`' + fields + '`) VALUES (\'' + values + '\')')
  }

  /* 
    删除数据

    conditions:object(条件)
  */
  async del(conditions) {
    let condition = Object.entries(conditions)
    let sql = ''
    for (let i in condition) {
      sql += ' AND `' + condition[i].join("`='") + '\''
    }
    return this.app.mysql.query('DELETE FROM `' + this.tableName + '` WHERE 1=1' + sql)
  }

  /* 
    修改数据

    options:object(修改的数据)
    conditions:object(条件)
  */
  async update(options, conditions) {
    let option = Object.entries(options)
    let optionSql = ''
    for (let i in option) {
      optionSql += ',`' + option[i].join("`='") + '\''
    }
    optionSql = optionSql.substr(1)

    let condition = Object.entries(conditions)
    let conditionSql = ''
    for (let i in condition) {
      conditionSql += ' AND `' + condition[i].join("`='") + '\''
    }

    return this.app.mysql.query('UPDATE `' + this.tableName + '` SET ' + optionSql + ' WHERE 1=1' + conditionSql)
  }

  /* 
    查询数据

    conditions:object(条件)
    fields:array(字段)
  */
  async consult(conditions, fields) {
    let condition = null
    let conditionSql = ''
    if (conditions) {
      condition = Object.entries(conditions)
      for (let i in condition) {
        conditionSql += ' AND `' + condition[i].join("`='") + '\''
      }
    }
    let sql = fields ? 'SELECT `' + fields.join("`,`") + '` FROM `' + this.tableName + '`' + ' WHERE 1=1' + conditionSql : 'SELECT * FROM `' + this.tableName + '`' + ' WHERE 1=1' + conditionSql
    return this.app.mysql.query(sql)
  }

  /* 
      查询数据
  
      conditions:object(条件)
      fields:array(字段)
      page: {
        curPage,  从url参数上 page参数获取  默认 1
        eachPage  每页显示条数
      }分页信息
    */
  async consultPage(conditions, fields, page) {
    let condition = null
    let conditionSql = ''
    if (conditions) {
      condition = Object.entries(conditions)
      for (let i in condition) {
        conditionSql += ' AND `' + condition[i].join("`='") + '\''
      }
    }

    let totalRow = await this.app.mysql.query('SELECT * FROM `' + this.tableName + '`' + ' WHERE 1=1' + conditionSql)
    let totalPage = Math.ceil(totalRow.length / page.eachPage) // 总页数

    let sql = fields ? 'SELECT `' + fields.join("`,`") + '` FROM `' + this.tableName + '`' + ' WHERE 1=1' + conditionSql : 'SELECT * FROM `' + this.tableName + '`' + ' WHERE 1=1' + conditionSql + ' LIMIT ' + ((page.curPage - 1) * page.eachPage) + ',' + page.eachPage

    let result = await this.app.mysql.query(sql)

    return { list: result, page: {totalRow: totalRow.length, totalPage} }
  }

  /* 
    模糊查询数据

    conditions:object(条件)
    fields:array(字段)
  */
  async vagueConsult(conditions, fields) {
    let condition = null
    let conditionSql = ''
    if (conditions) {
      condition = Object.entries(conditions)
      for (let i in condition) {
        conditionSql += ' AND `' + condition[i].join("` LIKE '%") + '%\''
      }
    }
    let sql = fields ? 'SELECT `' + fields.join("`,`") + '` FROM `' + this.tableName + '`' + ' WHERE 1=1' + conditionSql : 'SELECT * FROM `' + this.tableName + '`' + ' WHERE 1=1' + conditionSql
    return this.app.mysql.query(sql)
  }

  //图片上传
  async upload() {
    let file = this.ctx.request.files[0]
    const extension = file.filepath.split('.').pop();// 获取文件后缀
    //需要填写你的 Access Key 和 Secret Key
    qiniu.conf.ACCESS_KEY = 'Z3Bx0PUF2rWcjlhdRafqtLV_IzZx8JuDy1zf7jpH';
    qiniu.conf.SECRET_KEY = 'JqsdrxvwXQAINWlXX076me6c2Z_Al1uO-1ds4MqE';
    //要上传的空间
    let bucket = 'shop-qj12';
    // 自定义文件名 这里是以上传时间的md5为文件名
    let key = crypto.createHash('md5').update(new Date().getTime().toString()).digest('hex') + '.' + extension;
    //生成上传 Token
    const policy = new qiniu.rs.PutPolicy({ isPrefixalScope: 1, scope: bucket + ':' + key })
    let token = policy.uploadToken()
    // 上传
    let extra = new qiniu.form_up.PutExtra();
    const config = new qiniu.conf.Config()
    config.zone = qiniu.zone.Zone_z2;
    const formUploader = new qiniu.form_up.FormUploader(config);
    formUploader.putFile(token, key, file.filepath, extra, function (respErr, respBody, respInfo) {
      if (respErr) {
        throw respErr;
      }
      if (respInfo.statusCode == 200) {
        // console.log(respBody);
      } else {
        // console.log(respInfo.statusCode);
        // console.log(respBody);
      }
    });
    this.resData(0, '图片上传成功', { path: `http://shop-qj.eduaskcms.xin/${key}` })
  }

  //生成图片验证码
  async captcha() {
    let captcha_key = this.ctx.query.key || ''
    let captcha = svgCaptcha.create({
      size: 4,
      fontSize: 40,
      width: 100,
      ignoreChars: 'OoLi',
      height: 40,
      noise: 4,
      // background: `rgba(${Math.random() * 255},${Math.random() * 255},${Math.random() * 255})`,
      background: '#cc9966'
    })
    this.ctx.response.type = 'image/svg+xml'
    let key = crypto.createHash('md5').update(captcha.text.toLowerCase()).digest('hex')
    let code = captcha.text.toLowerCase()
    let expire = Date.now() + 1000 * 60 * 5
    await this.app.mysql.query('INSERT INTO `captcha` (`id`, `key`, `code`, `is_use`, `expire`) VALUES (?,?,?,?,?)', [null, key, code, 0, expire])
    await this.app.mysql.query('DELETE FROM `captcha` WHERE `key`=?', [captcha_key])
    this.resData(0, '图片验证码获取成功', { key, img: captcha.data })
  }

  //管理员/商户 登录
  async login() {
    const { ctx, app } = this
    let { username, password, captcha_code, captcha_key } = ctx.request.body
    password = crypto.createHash('md5').update(password).digest('hex')
    let ur = await app.mysql.query('SELECT * FROM `user` WHERE `username`=? AND `password`=?', [username, password])
    let cr = await app.mysql.query('SELECT * FROM `captcha` WHERE `code`=?', [captcha_code])

    if (!cr.length) {
      await app.mysql.query('UPDATE `captcha` SET `is_use`=? WHERE `key`=?', [1, captcha_key])
      return this.resData(1, '验证码错误', null)
    }

    if ((cr[0].expire < Date.now()) || cr[0].is_use) {
      return this.resData(2, '验证码已失效', null)
    }
    if (!ur.length) {
      await app.mysql.query('UPDATE `captcha` SET `is_use`=? WHERE `code`=?', [1, captcha_code])
      return this.resData(3, '用户名或密码错误', null)
    }

    await app.mysql.query('DELETE FROM `captcha` WHERE `key`=? OR `is_use`=? OR `expire`<?', [captcha_key, 1, Date.now()])
    await app.mysql.query('UPDATE `user` SET `login_time`=?, `login_ip`=? WHERE `username`=? AND `password`=?', [Date.now(), ctx.request.ip, username, password])
    return this.resData(0, '登录成功', { token: app.jwt.sign({ uid: ur[0].uid }, app.config.jwt.secret) })
  }

  //商品分类树
  async goodsCategoryTree() {

    this.tableName = 'goods_category'

    let all = await this.consult()

    let f = all.filter(item => item.pid === 0)

    let result = f.map(i1 => {
      let s = all.filter(i2 => i2.pid === i1.category_id)

      s = s.map(i3 => {
        let t = all.filter(i4 => i4.pid === i3.category_id)
        return {
          ...i3,
          children: t
        }
      })

      return {
        ...i1,
        children: s
      }
    })

    this.resData(0, '商品分类树获取成功', result)

  }

}

module.exports = CommonController;
